package com.hl.yyx.common.util;

import com.google.common.base.Joiner;
import com.hl.yyx.common.constants.CacheConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Collections;
import java.util.Objects;
import java.util.Set;


/**
 * @description redis 工具类
 */
@Component
@Slf4j
public class RedisUtil {

    @Autowired
    private JedisPool jedisPool;

    /**
     * redis默认缓存时间为5分钟
     */
    private Integer defaultTime = 300;

    private Jedis getResource() {
        return jedisPool.getResource();
    }

    /**
     * @param key,
     * @param value
     * @return java.lang.String
     * @description 缓存数据
     */
    public String set(String key, String value) {
        return set(key, value, defaultTime);
    }


    /**
     * @param key,
     * @param value
     * @return java.lang.String
     * @description 缓存数据
     */
    public String set(String key, String value, Integer timeout) {
        Jedis jedis = getResource();
        try {
            String set = jedis.set(key, value);
            if (timeout != null) {
                jedis.expire(key, timeout);
            }
            return set;
        } catch (Exception e) {
            log.info("redis异常,{}", e.getMessage());
            e.printStackTrace();
            log.error("redis异常,{}", e.getMessage());
        } finally {
            jedis.close();
        }
        return null;
    }

    /**
     * @param key
     * @return java.lang.String
     * @description 通过key取数据
     */
    public String get(String key) {
        Jedis jedis = getResource();
        try {
            return jedis.get(key);
        } finally {
            jedis.close();
        }
    }

    public byte[] set(byte[] key, byte[] value) {
        Jedis jedis = getResource();
        try {
            jedis.set(key, value);
            return value;
        } finally {
            jedis.close();
        }
    }

    public byte[] set(byte[] key, byte[] value, int expire) {
        Jedis jedis = getResource();
        try {
            jedis.set(key, value);
            jedis.expire(key, expire);
            return value;
        } finally {
            jedis.close();
        }
    }

    public void expire(byte[] key, int i) {
        Jedis jedis = getResource();
        try {
            jedis.expire(key, i);
        } finally {
            jedis.close();
        }
    }

    public void expire(String key, int i) {
        Jedis jedis = getResource();
        try {
            jedis.expire(key, i);
        } finally {
            jedis.close();
        }
    }

    public void incr(String key) {
        Jedis jedis = getResource();
        try {
            jedis.incr(key);
        } finally {
            jedis.close();
        }
    }

    public byte[] get(byte[] key) {
        Jedis jedis = getResource();
        try {
            return jedis.get(key);
        } finally {
            jedis.close();
        }
    }

    public void del(String key) {
        Jedis jedis = getResource();
        try {
            jedis.del(key);
        } finally {
            jedis.close();
        }
    }


    public void del(byte[] key) {
        Jedis jedis = getResource();
        try {
            jedis.del(key);
        } finally {
            jedis.close();
        }
    }

    public Set<byte[]> keys(String sHIRO_SESSION_PREFIX) {
        Jedis jedis = getResource();
        try {
            return jedis.keys((sHIRO_SESSION_PREFIX + "*").getBytes());
        } finally {
            jedis.close();
        }
    }

    /**
     * @param prefix 前缀
     * @param keys   key值
     * @return java.lang.String
     * @description 通过key，自动生成缓存前缀
     */
    public String generateCacheKey(CacheConstants prefix, String... keys) {
        String key = prefix.name();
        if (keys != null && keys.length > 0) {
            key += "_" + Joiner.on("_").join(keys);
        }
        return key;
    }

    /**
     * 获取分布式锁：
     * 获取锁，设置超时，执行任务之后必须进行删除
     *
     * @param key
     * @return
     */
    public boolean setnx(String key) {
        Jedis jedis = getResource();
        try {
            Long setnx = jedis.setnx(key, String.valueOf(1));
            if (setnx == 1) {
                // 强制设置30s的过期时间
                jedis.expire(key, 30);
                return true;
            } else {
                return false;
            }
        } finally {
            jedis.close();
        }
    }

    /**
     * 解分布式锁：
     * 获取锁，设置超时，执行任务之后必须进行删除
     *
     * @param key        加锁key
     * @return 加锁结果
     */
    public boolean unlock(String key) {
        // 获取redis连接池
        Jedis jedis = getResource();

        try {
            String lua = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end;";
            Object result = jedis.eval(lua, Collections.singletonList(key), Collections.singletonList(String.valueOf(Thread.currentThread().getId())));
            //判断是否成功
            return result.equals(1L);
        } catch (Exception e) {
            log.error("解redis分布式锁失败", e);
        }

        // 其他情况，均返回加锁失败
        return false;
    }

    /**
     * 获取key的剩余时间（秒）
     * @param key
     * @return
     */
    public Long ttl(String key) {
        try (Jedis jedis = getResource()) {
            return jedis.ttl(key);
        }
    }
}
